// @Author : zaniu(zzaniu@126.com)
// @Time   : 2021/9/1 15:26
// @Desc   : 分布式事务好鸡儿蛋疼啊....
//
//                   _ooOoo_
//                  o8888888o
//                  88" . "88
//                  (| -_- |)
//                  O\  =  /O
//               ____/`---'\____
//             .'  \\|     |//  `.
//            /  \\|||  :  |||//  \
//           /  _||||| -:- |||||-  \
//           |   | \\\  -  /// |   |
//           | \_|  ''\---/''  |   |
//           \  .-\__  `-`  ___/-. /
//         ___`. .'  /--.--\  `. . __
//      ."" '<  `.___\_<|>_/___.'  >'"".
//     | | :  `- \`.;`\ _ /`;.`/ - ` : | |
//     \  \ `-.   \_ __\ /__ _/   .-` /  /
// =====`-.____`-.___\_____/___.-`____.-'=====
//                   `=---='
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//           佛祖保佑       永无BUG
//
package main

import (
	"context"
	"distributedTransaction/client/conf"
	"distributedTransaction/client/middleware"
	"distributedTransaction/client/order"
	"distributedTransaction/client/user"
	"distributedTransaction/utils"
	"distributedTransaction/utils/client"
	"distributedTransaction/utils/nacos"
	"fmt"
	"github.com/gin-gonic/gin"
	"github.com/nacos-group/nacos-sdk-go/model"
	"log"
	"net/http"
	"os"
	"os/signal"
	"time"
)

// TODO 这里可以使用闭包包一层，后续有空再实现
// slice 不是并发安全的，必须加锁，否则数据会丢失
func UserSubscribeServerCallBack(services []model.SubscribeService, err error) {
	conf.RWLock.Lock()
	defer conf.RWLock.Unlock()
	conf.GlobalUserServices = []conf.RpcServerInfo{}
	for _, service := range services {
		conf.GlobalUserServices = append(conf.GlobalUserServices, conf.RpcServerInfo{Ip: service.Ip, Port: service.Port})
	}
}

func UserUnsubscribeServerCallBack(services []model.SubscribeService, err error) {
	conf.RWLock.Lock()
	defer conf.RWLock.Unlock()
	conf.GlobalUserServices = []conf.RpcServerInfo{}
}

func OrderSubscribeServerCallBack(services []model.SubscribeService, err error) {
	conf.RWLock.Lock()
	defer conf.RWLock.Unlock()
	conf.GlobalOrderServices = []conf.RpcServerInfo{}
	for _, service := range services {
		conf.GlobalOrderServices = append(conf.GlobalOrderServices, conf.RpcServerInfo{Ip: service.Ip, Port: service.Port})
	}
}

func OrderUnsubscribeServerCallBack(services []model.SubscribeService, err error) {
	conf.RWLock.Lock()
	defer conf.RWLock.Unlock()
	conf.GlobalOrderServices = []conf.RpcServerInfo{}
}

func InventorySubscribeServerCallBack(services []model.SubscribeService, err error) {
	conf.RWLock.Lock()
	defer conf.RWLock.Unlock()
	conf.GlobalInventoryServices = []conf.RpcServerInfo{}
	for _, service := range services {
		conf.GlobalInventoryServices = append(conf.GlobalInventoryServices, conf.RpcServerInfo{Ip: service.Ip, Port: service.Port})
	}
}

func InventoryUnsubscribeServerCallBack(services []model.SubscribeService, err error) {
	conf.RWLock.Lock()
	defer conf.RWLock.Unlock()
	conf.GlobalInventoryServices = []conf.RpcServerInfo{}
}

func SubscribeUserServer() {
	err := nacos.SubscribeServer("gmb.go.user", "", "", UserSubscribeServerCallBack)
	if err != nil {
		fmt.Println("监听注册中心失败")
		panic(err)
	}
}

func UnSubscribeUserServer() {
	nacos.Unsubscribe("gmb.go.user", "", "", UserUnsubscribeServerCallBack)
}

func SubscribeOrderServer() {
	err := nacos.SubscribeServer("gmb.go.order", "", "", OrderSubscribeServerCallBack)
	if err != nil {
		fmt.Println("监听注册中心失败")
		panic(err)
	}
}

func UnSubscribeOrderServer() {
	nacos.Unsubscribe("gmb.go.order", "", "", OrderUnsubscribeServerCallBack)
}

func SubscribeInventoryServer() {
	err := nacos.SubscribeServer("gmb.go.inventory", "", "", InventorySubscribeServerCallBack)
	if err != nil {
		fmt.Println("监听注册中心失败")
		panic(err)
	}
}

func UnSubscribeInventoryServer() {
	nacos.Unsubscribe("gmb.go.inventory", "", "", InventoryUnsubscribeServerCallBack)
}

func SubscribeServer() {
	SubscribeUserServer()
	SubscribeOrderServer()
	SubscribeInventoryServer()
}

func UnSubscribeServer() {
	UnSubscribeUserServer()
	UnSubscribeOrderServer()
	UnSubscribeInventoryServer()
}

func main() {
	nacos.ListenServerConfig("dev-data", "dev-group", &utils.GlobalServerConfig)
	SubscribeServer()
	client.Rocket = client.StartTransactionProducer()
	router := gin.Default()
	router.Use()
	router.POST("/login", user.Login)
	router.Use(middleware.JWTAuth())
	orderRouter := router.Group("/order")
	{
		orderRouter.GET("/QueryOrder", order.QueryOrder)
		orderRouter.GET("/QueryOrder/:globalNo", order.QueryOrder)
		orderRouter.POST("/PlaceOrder", order.PlaceOrder)
	}

	s := &http.Server{
		Addr:           "0.0.0.0:3456",
		Handler:        router,
		ReadTimeout:    5 * time.Second,
		WriteTimeout:   5 * time.Second,
		MaxHeaderBytes: 1 << 20,
	}
	go func() {
		if err := s.ListenAndServe(); err != nil && err != http.ErrServerClosed {
			log.Fatalf("listen: %s\n", err)
		}
	}()
	quit := make(chan os.Signal)
	signal.Notify(quit, os.Interrupt)
	<-quit
	UnSubscribeServer()
	nacos.CancelListenConfig("dev-data", "dev-group")
	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
	defer cancel()
	if err := s.Shutdown(ctx); err != nil {
		log.Fatal("Server Shutdown:", err)
	}
	// 停止RocketMQ监听
	(*client.Rocket).Shutdown()
	log.Println("Server exiting")
}
